# test_room.gd
extends Node2D
class_name Room
@onready var enemy_spwan_timer: Timer = $EnemySpwanTimer
@onready var ally_spwan_timer: Timer = $AllySpwanTimer
@onready var ally_born_area: Polygon2D = $AllyBornArea

# 房间配置
@export var room_size := Vector2(1152, 640) # 在检查器可调整
@export var spawn_point_count := 3 # 每方出生点数量
@export var wall_width := 16 # 与墙壁保持的距离
@export var my_rect := Rect2(
	wall_width * 3,
	room_size.y - 200 - wall_width * 3,
	200,
	200
)

@export var enemy_rect := Rect2(
	room_size.x - 200 - wall_width * 3,
	wall_width * 3,
	200,
	200
)

var ally_spwan_points: Array[Vector2] = [] # 我方出生点数组
var enemy_spwan_points: Array[Vector2] = [] # 敌方出生点数组
@onready var all_ally_spwaned := false
@onready var all_enemy_spwaned := false

var enemy_spwan_cooldown := 1.0
var ally_spwan_cooldown := 1.0

@onready var remain_enemies: Dictionary = GameData.level_data.room_queue.duplicate()[GameData.level_data.room_index - 1]
@onready var remain_ally: Array = GameData.army_data.to_dict().get("troops", []).duplicate()

var grid_polygons: Array[Polygon2D] = []

var selection_polygon: Polygon2D = null
var selected_troop: String = "" # 当前选中的兵种
var snap_size: int = 32 # 吸附大小
var selected_areas: Array = [] # 已选择的区域数组
var born_area_rect: Rect2
var is_selecting_born_area: bool
var last_scroll_time: float = 0.0


func _ready():
	GlobalSignal.gs_room_ready.emit(self)
	GlobalSignal.gs_unit_died.connect(_on_unit_died)
	_init_available_troops()
	_init_selection_area()
	## 生成出生点
	#_generate_spawn_areas()
	#
	## 设置相机
	#_setup_camera()
#
	## 添加出生点标记
	#_add_spawn_markers()
	#
	## 初始化计时器
	#enemy_spwan_timer.wait_time = enemy_spwan_cooldown
	#ally_spwan_timer.wait_time = ally_spwan_cooldown
	#enemy_spwan_timer.timeout.connect(_spawn_enemy_wave)
	#ally_spwan_timer.timeout.connect(_spawn_ally_wave)
	#enemy_spwan_timer.start()
	#ally_spwan_timer.start()
	#all_ally_spwaned = false
	#all_enemy_spwaned = false

# 初始化可用兵种卡片
func _init_available_troops():
	var available_troops_container = $CanvasLayer/AvailableTroops
	for troop_type in GameData.available_troop_types:
		var troop_card = _create_troop_card(troop_type)
		available_troops_container.add_child(troop_card)

# 创建兵种卡片
func _create_troop_card(troop_type: String) -> Control:
	var troop_card = Button.new()
	troop_card.text = troop_type
	troop_card.pressed.connect(func():
		_on_troop_card_pressed(troop_type)
	)
	return troop_card

# 处理兵种卡片点击事件
func _on_troop_card_pressed(troop_type):
	is_selecting_born_area = true
	selected_troop = troop_type
	var troop_type_data = GameData.all_troop_types.get(troop_type)
	selection_polygon.color = troop_type_data.get("background_color", Color(1, 1, 1))

# 初始化选择区域
func _init_selection_area():
	var polygon = ally_born_area.polygon
	var min_x = polygon[0].x
	var min_y = polygon[0].y
	var max_x = min_x
	var max_y = min_y
	for point in polygon:
			min_x = min(min_x, point.x)
			min_y = min(min_y, point.y)
			max_x = max(max_x, point.x)
			max_y = max(max_y, point.y)
	born_area_rect = Rect2(Vector2(min_x, min_y), Vector2(max_x - min_x, max_y - min_y))
	selection_polygon = Polygon2D.new()
	selection_polygon.visible = false
	selection_polygon.polygon = PackedVector2Array([
				Vector2(0, 0),
				Vector2(snap_size, 0),
				Vector2(snap_size, snap_size),
				Vector2(0, snap_size)
			])
	add_child(selection_polygon)
	# 添加外边框
	var border_line = Line2D.new()
	border_line.width = 1
	border_line.default_color = Color(1, 0, 0) # 红色外边框
	for i in range(polygon.size()):
		border_line.add_point(polygon[i])
	border_line.add_point(polygon[0])
	add_child(border_line)
	
	# 添加网格
	_add_grid(born_area_rect)

# 添加网格
func _add_grid(rect: Rect2):
	var min_x = rect.position.x
	var min_y = rect.position.y
	var max_x = rect.end.x
	var max_y = rect.end.y
	grid_polygons.clear()


	# 绘制水平网格线
	for y in range(int(min_y) + 1, int(max_y), snap_size):
		var grid_line = Line2D.new()
		grid_line.width = 1
		grid_line.default_color = Color(0.5, 0.5, 0.5) # 灰色网格线
		add_child(grid_line)
		grid_line.add_point(Vector2(min_x, y))
		grid_line.add_point(Vector2(max_x, y))
	
	# 绘制垂直网格线
	for x in range(int(min_x) + 1, int(max_x), snap_size):
		var grid_line = Line2D.new()
		grid_line.width = 1
		grid_line.default_color = Color(0.5, 0.5, 0.5) # 灰色网格线
		add_child(grid_line)
		grid_line.add_point(Vector2(x, min_y))
		grid_line.add_point(Vector2(x, max_y))


			# 创建栅格多边形
	for y in range(int(min_y), int(max_y), snap_size):
		for x in range(int(min_x), int(max_x), snap_size):
			var polygon = Polygon2D.new()
			polygon.polygon = PackedVector2Array([
				Vector2(x, y),
				Vector2(x + snap_size, y),
				Vector2(x + snap_size, y + snap_size),
				Vector2(x, y + snap_size)
			])
			polygon.color = Color(1, 0, 0, 0.0) # 初始透明度为0
			grid_polygons.append(polygon)
			add_child(polygon)
# 初始化选择区域


# 取消选择区域
func _cancel_selection():
	is_selecting_born_area = false
	selection_polygon.visible = false
	# 重置所有栅格多边形的透明度
	for polygon in grid_polygons:
		polygon.color.a = 0.0

# 删除最后一个选择区域
func _undo_last_selection():
	if selected_areas.is_empty():
		push_warning("没有可撤销的选择区域。")
		return
	
	# 移除最后一个选择区域
	selected_areas.pop_back()
	# 重置所有栅格多边形的透明度
	for polygon in grid_polygons:
		polygon.color.a = 0.0

# 处理鼠标按下事件
func _input(event):
	if event is InputEventKey:
		if event.pressed and event.keycode == KEY_ESCAPE:
			_cancel_selection()
		if event.pressed and event.keycode == KEY_Z and event.is_command_or_control_pressed():
			_undo_last_selection()
	elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		if is_selecting_born_area and born_area_rect.has_point(event.global_position):
			# 结束选择区域并保存
			_save_selection()

	elif event is InputEventMouseMotion:
		if is_selecting_born_area and born_area_rect.has_point(event.position):
			selection_polygon.visible = true
			# 获取当前鼠标全局位置
			var current_mouse_pos = get_global_mouse_position()
			# 更新多边形数据
			var polygon_size = selection_polygon.polygon[2]
			var new_position = (current_mouse_pos - polygon_size / 2).snapped(Vector2(snap_size, snap_size))
			new_position.x = clamp(new_position.x, born_area_rect.position.x, born_area_rect.end.x - polygon_size.x)
			new_position.y = clamp(new_position.y, born_area_rect.position.y, born_area_rect.end.y - polygon_size.y)
			selection_polygon.position = new_position
			# 检测重叠区域
			var polygon = []
			for p in selection_polygon.polygon:
				polygon.append(p + selection_polygon.position)
			
			polygon = PackedVector2Array(polygon)
			var overlaps = get_area_overlaps(polygon)
			
			# 调整栅格多边形的透明度
			for grid_polygon in grid_polygons:
				var is_overlapping = false
				for overlap in overlaps:
					if Geometry2D.intersect_polygons(grid_polygon.polygon, overlap).size() > 0:
						is_overlapping = true
						break
				if is_overlapping:
					grid_polygon.color.a = 0.5 # 透明度为0.5
				else:
					grid_polygon.color.a = 0.0 # 透明度为0
		else:
			selection_polygon.visible = false
			# 重置所有栅格多边形的透明度
			for grid_polygon in grid_polygons:
				grid_polygon.color.a = 0.0

	elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_WHEEL_UP:
		if is_selecting_born_area and (Time.get_ticks_msec() - last_scroll_time) > GameConstant.SCROLL_DEBOUNCE_TIME * 1000:
			# 增加选择区域大小
			var current_size = selection_polygon.polygon[2]
			var new_size = (current_size + Vector2(snap_size, snap_size)).clamp(Vector2(snap_size, snap_size), Vector2(snap_size * 4, snap_size * 4))
			selection_polygon.polygon = PackedVector2Array([
				Vector2(0, 0),
				Vector2(new_size.x, 0),
				new_size,
				Vector2(0, new_size.y)
			])
			last_scroll_time = Time.get_ticks_msec()

	elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
		if is_selecting_born_area and (Time.get_ticks_msec() - last_scroll_time) > GameConstant.SCROLL_DEBOUNCE_TIME * 1000:
			# 减少选择区域大小
			var current_size = selection_polygon.polygon[2]
			var new_size = (current_size - Vector2(snap_size, snap_size)).clamp(Vector2(snap_size, snap_size), Vector2(snap_size * 4, snap_size * 4))
			selection_polygon.polygon = PackedVector2Array([
				Vector2(0, 0),
				Vector2(new_size.x, 0),
				new_size,
				Vector2(0, new_size.y)
			])
			last_scroll_time = Time.get_ticks_msec()

# 保存选择的多边形和兵种信息
func _save_selection():
	if selected_troop == "":
		is_selecting_born_area = false
		return
	
	# 获取最终选择的多边形
	var polygon = []
	for p in selection_polygon.polygon:
		polygon.append(p + selection_polygon.position)
	
	# 将普通数组转换回 PackedVector2Array
	polygon = PackedVector2Array(polygon)
	
	# 检查是否已选择该区域
	var overlaps = get_area_overlaps(polygon)
	if overlaps.size() > 0:
		push_warning("该区域已被选择，请选择其他区域")
		return
	# 获取选中的兵种数据
	var troop_type_data = GameData.all_troop_types.get(selected_troop)
	if not troop_type_data:
		push_error("兵种数据未找到: ", selected_troop)
		return
	
	# 获取兵种的icon路径
	var icon_path = troop_type_data.get("icon_path")
	if not icon_path or not ResourceLoader.exists(icon_path):
		push_error("兵种图标路径无效或不存在: ", icon_path)
		return
	
	# 加载兵种图标
	var icon_texture = load(icon_path) as Texture2D
	if not icon_texture:
		push_error("无法加载兵种图标: ", icon_path)
		return
	
	# 计算放置图标的起始位置
	var start_pos = polygon[0]
	var current_pos = start_pos
	
	# 计算多边形的边界框
	var bounds = _get_polygon_bounds(polygon)
	
	# 在多边形内放置图标
	while current_pos.x < bounds.end.x:
		var row_start = current_pos
		while row_start.y < bounds.end.y:
			# 检查点是否在多边形内
			if Geometry2D.is_point_in_polygon(row_start, polygon):
				var texture_rect = TextureRect.new()
				texture_rect.texture = icon_texture
				texture_rect.custom_minimum_size = Vector2(snap_size, snap_size)
				texture_rect.global_position = row_start
				add_child(texture_rect)
			
			row_start.y += snap_size
		
		current_pos.x += snap_size
	
	# 保存选择的兵种和多边形信息
	var selection_data = {
		"troop": selected_troop,
		"polygon": polygon
	}
	
	# 添加到已选择区域数组
	selected_areas.append(selection_data)
	
	# 可以将 selection_data 存储到全局数据或发送信号
	
	# 隐藏选择区域
	#is_selecting_born_area = false

# 检查是否有重复区域并返回所有重叠部分
func get_area_overlaps(polygon: PackedVector2Array) -> Array:
	var overlaps = []

	for area in selected_areas:
		var overlap = _get_polygon_overlap(area.polygon, polygon)
		if not overlap.is_empty():
			overlaps.append(overlap)
	
	return overlaps

# 获取两个多边形的重叠区域
func _get_polygon_overlap(p1: PackedVector2Array, p2: PackedVector2Array) -> PackedVector2Array:
	# 1. 先用边界框快速排除不重叠的情况
	var rect1 = _get_polygon_bounds(p1)
	var rect2 = _get_polygon_bounds(p2)
	if not rect1.intersects(rect2):
		return PackedVector2Array()
	# 2. 计算多边形的交集
	var intersections = Geometry2D.intersect_polygons(p1, p2)
	# 返回第一个交集区域（如果有）
	if intersections.size() > 0:
		return intersections[0]
	return PackedVector2Array()

# 获取多边形的边界框
func _get_polygon_bounds(polygon: PackedVector2Array) -> Rect2:
	if polygon.is_empty():
		return Rect2()
	
	var min_x = polygon[0].x
	var min_y = polygon[0].y
	var max_x = polygon[0].x
	var max_y = polygon[0].y
	
	for point in polygon:
		min_x = min(min_x, point.x)
		min_y = min(min_y, point.y)
		max_x = max(max_x, point.x)
		max_y = max(max_y, point.y)
	
	return Rect2(Vector2(min_x, min_y), Vector2(max_x - min_x, max_y - min_y))

func _spawn_enemy_wave():
	var spawn_count = enemy_spwan_points.size()
	if spawn_count == 0:
		return
	
	# 按优先级顺序生成
	var categories = ["normal", "elite", "boss"]
	var spawned = 0
	
	for category in categories:
		var units = remain_enemies.get(category, {})
		if units.is_empty():
			continue
		
		# 获取可用单位类型
		var available_types = units.keys().filter(func(k): return units[k] > 0)
		if available_types.is_empty():
			continue
		
		# 随机选择类型
		var selected_type = available_types.pick_random()
		var max_spawn = min(units[selected_type], spawn_count - spawned)
		
		# 生成单位
		for i in range(max_spawn):
			var spawn_point = enemy_spwan_points[spawned + i]
			_create_enemy(category, selected_type, spawn_point)
		
		# 更新数据
		remain_enemies[category][selected_type] -= max_spawn
		if remain_enemies[category][selected_type] <= 0:
			remain_enemies[category].erase(selected_type)
		
		spawned += max_spawn
		if spawned >= spawn_count:
			break
	
	# 检查是否还有剩余敌人
	if _is_enemy_data_empty():
		enemy_spwan_timer.stop()

	# 在 _spawn_enemy_wave 函数末尾添加：
	if enemy_spwan_timer.is_stopped() and not all_enemy_spwaned:
		all_enemy_spwaned = true
		#GlobalSignal.gs_all_enemy_spwaned.emit() # 可以发送全局信号

func _spawn_ally_wave():
	var spawn_count = ally_spwan_points.size()
	if spawn_count == 0 or remain_ally.is_empty():
		return
	
	# 过滤可用单位并计算剩余总数
	var available_units = remain_ally.filter(func(u): return u["count"] > 0)
	var total_available = available_units.reduce(func(acc, u): return acc + u["count"], 0)
	if available_units.is_empty() or total_available <= 0:
		ally_spwan_timer.stop()
		return
	
	var max_spawn = min(total_available, spawn_count) # 实际可生成上限
	
	for i in range(max_spawn):
		if i >= ally_spwan_points.size():
			break
		
		# 更新可用单位列表
		available_units = remain_ally.filter(func(u): return u["count"] > 0)
		if available_units.is_empty():
			break
		
		# 随机选择兵种
		var selected = available_units.pick_random()
		var spawn_point = ally_spwan_points[i]
		
		# 生成单位
		_create_ally(selected, spawn_point)
		
		# 更新数据
		selected["count"] -= 1
		
		# 清理空单位
		if selected["count"] <= 0:
			remain_ally.erase(selected)
	
	# 最终检查剩余
	if remain_ally.all(func(u): return u["count"] <= 0):
		ally_spwan_timer.stop()

	if ally_spwan_timer.is_stopped() and not all_ally_spwaned:
		all_ally_spwaned = true

func _create_enemy(category: String, selected_type: String, spawn_pos: Vector2):
	var scene_path = _get_enemy_scene_path(category, selected_type)
	if not ResourceLoader.exists(scene_path):
		push_error("Enemy scene not found: ", scene_path)
		return
	
	var enemy = load(scene_path).instantiate()
	enemy.global_position = spawn_pos
	add_child(enemy)

func _create_ally(ally_data: Dictionary, spawn_pos: Vector2):
	if not ResourceLoader.exists(ally_data["scene_path"]):
		push_error("Ally scene not found: ", ally_data["scene_path"])
		return
	
	var ally = load(ally_data["scene_path"]).instantiate()
	ally.global_position = spawn_pos
	add_child(ally)

func _get_enemy_scene_path(category: String, enemy_type: String) -> String:
	# 定义类别映射字典
	var category_map = {
		"normal": GameData.normal_enemies,
		"elite": GameData.elite_enemies,
		"boss": GameData.boss_enemies
	}
	
	# 获取对应类别的敌人数据
	var enemy_data = category_map.get(category, {})
	if enemy_data.is_empty():
		push_error("Invalid enemy category: ", category)
		return ""
	
	# 获取具体敌人配置
	var config = enemy_data.get(enemy_type, {})
	if config.is_empty():
		push_error("Enemy type not found: ", enemy_type, " in category: ", category)
		return ""
	
	# 验证场景路径
	var path = config.get("scene_path", "")
	if not ResourceLoader.exists(path):
		push_error("Scene path not found for ", enemy_type, " (", category, "): ", path)
		return ""
	
	return path

func _is_enemy_data_empty() -> bool:
	return (
		remain_enemies["normal"].is_empty() and
		remain_enemies["elite"].is_empty() and
		remain_enemies["boss"].is_empty()
	)

func _generate_spawn_areas():
	var rng = RandomNumberGenerator.new()
	

	# 生成非重叠点
	ally_spwan_points = _generate_non_overlapping_points(rng, my_rect)
	enemy_spwan_points = _generate_non_overlapping_points(rng, enemy_rect)

func _generate_non_overlapping_points(rng: RandomNumberGenerator, area: Rect2) -> Array[Vector2]:
	var points: Array[Vector2] = []
	var attempt = 0
	const MIN_DISTANCE = 64 # 最小间距64像素
	const MAX_ATTEMPTS = 100
	
	while points.size() < spawn_point_count and attempt < MAX_ATTEMPTS:
		attempt += 1
		var new_point = Vector2(
			rng.randf_range(area.position.x, area.end.x),
			rng.randf_range(area.position.y, area.end.y)
		)
		
		# 检查是否与现有点太近
		var too_close = points.any(func(p):
			return p.distance_to(new_point) < MIN_DISTANCE
		)
		
		# 检查是否在墙内
		var in_wall = (
			new_point.x < wall_width or
			new_point.x > room_size.x - wall_width or
			new_point.y < wall_width or
			new_point.y > room_size.y - wall_width
		)
		
		if not too_close and not in_wall:
			points.append(new_point)
			attempt = 0
			
	if points.size() < spawn_point_count:
		push_warning("无法生成足够非重叠出生点，实际生成：%d" % points.size())
	
	return points


func _random_point_in_rect(rng: RandomNumberGenerator, rect: Rect2) -> Vector2:
	return Vector2(
		rng.randf_range(rect.position.x, rect.end.x),
		rng.randf_range(rect.position.y, rect.end.y)
	)

func _setup_camera():
	var camera = get_viewport().get_camera_2d()
	if camera:
		# 仅当房间超过屏幕尺寸时调整
		if room_size.x > 1152 || room_size.y > 640:
			if ally_spwan_points.size() > 0:
				# 取第一个出生点作为参考点
				var target_pos = ally_spwan_points[0]
				camera.position = target_pos
				
				# 设置相机边界限制
				camera.limit_left = wall_width
				camera.limit_top = wall_width
				camera.limit_right = room_size.x - wall_width
				camera.limit_bottom = room_size.y - wall_width

# 在 test_room.gd 中添加以下内容
func _add_spawn_markers():
	# 加载资源（添加失败保护）
	var ally_texture = load("res://game/03_assets/tilesets/ally_born_place.png") if ResourceLoader.exists("res://game/03_assets/tilesets/ally_born_place.png") else null
	var enemy_texture = load("res://game/03_assets/tilesets/enemy_born_place.png") if ResourceLoader.exists("res://game/03_assets/tilesets/enemy_born_place.png") else null
	
	# 创建标记父节点（方便后期管理）
	var marker_container = Node2D.new()
	marker_container.name = "SpawnMarkers"
	add_child(marker_container)

	# 生成我方标记
	for point in ally_spwan_points:
		var sprite = _create_marker_sprite(ally_texture, Color.GREEN)
		sprite.position = point
		marker_container.add_child(sprite)

	# 生成敌方标记
	for point in enemy_spwan_points:
		var sprite = _create_marker_sprite(enemy_texture, Color.RED)
		sprite.position = point
		marker_container.add_child(sprite)

func _create_marker_sprite(texture: Texture2D, fallback_color: Color) -> Sprite2D:
	var sprite = Sprite2D.new()
	sprite.texture = texture
	sprite.centered = true
	sprite.scale = Vector2.ONE * 2 # 16px -> 32px显示
	
	# 无纹理时用色块代替
	if not texture:
		var color_rect = ColorRect.new()
		color_rect.color = fallback_color
		color_rect.size = Vector2(16, 16)
		sprite.add_child(color_rect)
		push_warning("出生点图标加载失败，使用色块替代")
	
	return sprite

func _on_unit_died(unit: Unit) -> void:
	if unit.is_in_group("ally"):
		if all_ally_spwaned:
			var check_allies = get_tree().get_nodes_in_group("ally").filter(func(u): return u.is_alive())
			if check_allies.size() > 0:
				return
			get_tree().change_scene_to_file("res://game/01_scenes/interface/main_menu.tscn")
	if unit.is_in_group("enemy"):
		if all_enemy_spwaned:
			var check_enemies = get_tree().get_nodes_in_group("enemy").filter(func(u): return u.is_alive())
			if check_enemies.size() > 0:
				return

			var level_data = GameData.level_data
			if level_data.room_index == 6:
				level_data.level_number += 1
				level_data.room_index = 1
				get_tree().change_scene_to_file("res://game/01_scenes/interface/technology_select/technology_select.tscn")
			else:
				level_data.room_index += 1
				get_tree().change_scene_to_file("res://game/01_scenes/interface/army_deployment/army_deployment.tscn")
